package com.tm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tm.entity.AggsModel;
import com.tm.entity.Product;
import com.tm.service.ProductService;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedAvg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * Created by lichuan on 2022-09-19.
 */
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public Object saveProd(Product product) {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        IndexRequest indexRequest = new IndexRequest("product");
        indexRequest.id(uuid);
        indexRequest.source(JSONObject.toJSONString(product), XContentType.JSON);
        try {
            IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            RestStatus status = index.status();
            if (status == RestStatus.CREATED) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Object updateProd(Product product) {

        UpdateRequest updateRequest = new UpdateRequest("product",product.getId());
        updateRequest.doc(JSONObject.toJSONString(product),XContentType.JSON);
        try {
            UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            RestStatus status = update.status();
            if (RestStatus.OK == status) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Object del(Product product) {
        DeleteRequest request = new DeleteRequest("product",product.getId());

//        updateRequest.doc(JSONObject.toJSONString(product),XContentType.JSON);
        try {
            DeleteResponse update = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
            RestStatus status = update.status();
            if (RestStatus.OK == status) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Object getProd(Product product) {

        List<Product> list = new ArrayList<>();
        SearchRequest searchRequest= new SearchRequest("product");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("spuName", product.getSpuName());
        searchSourceBuilder.query(matchQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = search.getHits().getHits();

            for (int i = 0; i <hits.length ; i++) {
                Product product1 = new Product();
                product1.setId(hits[i].getId());
                product1.setSpuName(hits[i].getSourceAsMap().getOrDefault("spuName","")+"");
                list.add(product1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public Object getCeshi() {
        List<Map<String,Object>> list = new ArrayList<>();
        SearchRequest searchRequest= new SearchRequest("tianma12");

        //query
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //bool
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("address", "mill");
        //must
        boolQueryBuilder.must(matchQueryBuilder);

        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("balance").gte(10).lte(10000);
        //filter
        boolQueryBuilder.filter(rangeQueryBuilder);

        searchSourceBuilder.query(boolQueryBuilder);

        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            System.out.println(JSONObject.toJSONString(search));
            SearchHit[] hits = search.getHits().getHits();

            for (int i = 0; i <hits.length ; i++) {
                Map<String, Object> sourceAsMap = hits[i].getSourceAsMap();
                sourceAsMap.put("id",hits[i].getId());
                list.add(sourceAsMap);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public Object getAggr() {
        List<Map<String,Object>> list = new ArrayList<>();
        SearchRequest searchRequest= new SearchRequest("tianma12");

        //query
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("age_agg").field("age").size(100);

        TermsAggregationBuilder termsAggregationBuilder1 = AggregationBuilders.terms("gender_agg").field("gender.keyword").size(2);

        AvgAggregationBuilder field = AggregationBuilders.avg("balance_avg").field("balance");
        termsAggregationBuilder1.subAggregation(field);

        AvgAggregationBuilder field2 = AggregationBuilders.avg("balance_avg").field("balance");


        termsAggregationBuilder.subAggregation(termsAggregationBuilder1);
        termsAggregationBuilder.subAggregation(field2);
        searchSourceBuilder.aggregation(termsAggregationBuilder);
        searchSourceBuilder.size(0);

        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//            Aggregations aggregations = search.getAggregations();
//            List<Aggregation> aggregations1 = aggregations.asList();
            Map<String, Aggregation> asMap = search.getAggregations().getAsMap();
            ParsedLongTerms age_agg = (ParsedLongTerms) asMap.get("age_agg");
            List<? extends Terms.Bucket> buckets = age_agg.getBuckets();
            List<AggsModel> resList = new ArrayList<>();
            //根据年龄分组
            for (Terms.Bucket bucket : buckets) {
                AggsModel aggsModel = new AggsModel();
                ParsedLongTerms.ParsedBucket bucket1 = (ParsedLongTerms.ParsedBucket) bucket;
                long docCount = bucket1.getDocCount();
                aggsModel.setKey(bucket1.getKeyAsString());
                aggsModel.setDoc_count((int) docCount);
                Map<String, Aggregation> stringAggregationMap = bucket1.getAggregations().asMap();
                ParsedAvg balance_avg = (ParsedAvg) stringAggregationMap.get("balance_avg");
                double value = balance_avg.getValue();
                aggsModel.setBalance_avg(value);
                ParsedStringTerms stringTerms= (ParsedStringTerms) stringAggregationMap.get("gender_agg");
                List<? extends Terms.Bucket> buckets1 = stringTerms.getBuckets();

                List<AggsModel> aggsModels2 = new ArrayList<>();
                for (Terms.Bucket bucket2 : buckets1) {
                    AggsModel aggsModel1 = new AggsModel();
                    ParsedAvg saa = (ParsedAvg)  bucket2
                            .getAggregations()
                            .getAsMap()
                            .get("balance_avg");
                    aggsModel1.setKey(bucket2.getKeyAsString());
                    aggsModel1.setDoc_count((int) bucket2.getDocCount());
                    aggsModel1.setBalance_avg(saa.getValue());
                    aggsModels2.add(aggsModel1);
                }
                aggsModel.setGender_agg(aggsModels2);
                resList.add(aggsModel);
            }

            return resList;

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


}
